import { render, fireEvent } from "@testing-library/react";
import { Provider } from "mobx-react";
import { SkipButton } from "../buttons";

jest.mock("@humansignal/ui", () => {
  const { forwardRef } = jest.requireActual("react");
  return {
    Button: forwardRef(({ children, disabled, tooltip, onClick, ...props }: any, ref: any) => {
      return (
        <button {...props} ref={ref} data-testid="skip-button" disabled={disabled} title={tooltip} onClick={onClick}>
          {children}
        </button>
      );
    }),
    Tooltip: ({ children, title }: any) => {
      return (
        <div data-testid="tooltip" title={title}>
          {children}
        </div>
      );
    },
  };
});

jest.mock("@humansignal/icons", () => ({
  IconInfoOutline: ({ width, height, className }: any) => (
    <svg data-testid="info-icon" width={width} height={height} className={className} />
  ),
}));

const createMockStore = (overrides: any = {}) => ({
  task: { id: 1, allow_skip: true, ...overrides.task },
  skipTask: jest.fn(),
  hasInterface: jest.fn((name: string) => overrides.interfaces?.includes(name) ?? false),
  annotationStore: {
    selected: {
      submissionInProgress: jest.fn(),
    },
  },
  commentStore: {
    commentFormSubmit: jest.fn(),
  },
  ...overrides,
});

// Helper to set up window.APP_SETTINGS for role-based tests
const setupAppSettings = (role?: string) => {
  (window as any).APP_SETTINGS = {
    user: {
      role,
    },
  };
};

describe("SkipButton", () => {
  beforeEach(() => {
    jest.clearAllMocks();
    // Reset APP_SETTINGS before each test
    (window as any).APP_SETTINGS = undefined;
  });

  test("Skip button disabled when allow_skip=false", () => {
    const mockStore = createMockStore({
      task: { id: 1, allow_skip: false },
    });
    const onSkipWithComment = jest.fn();

    const { getByTestId } = render(
      <Provider store={mockStore}>
        <SkipButton disabled={false} store={mockStore as any} onSkipWithComment={onSkipWithComment} />
      </Provider>,
    );

    const button = getByTestId("skip-button");
    expect(button).toBeDisabled();
    expect(button).toHaveAttribute("title", "This task cannot be skipped");
  });

  test("Skip button enabled when allow_skip=true", () => {
    const mockStore = createMockStore({
      task: { id: 1, allow_skip: true },
    });
    const onSkipWithComment = jest.fn();

    const { getByTestId } = render(
      <Provider store={mockStore}>
        <SkipButton disabled={false} store={mockStore as any} onSkipWithComment={onSkipWithComment} />
      </Provider>,
    );

    const button = getByTestId("skip-button");
    expect(button).not.toBeDisabled();
    expect(button).toHaveAttribute("title", "Cancel (skip) task [ Ctrl+Space ]");
  });

  test("Skip button enabled when allow_skip is undefined (default behavior)", () => {
    const mockStore = createMockStore({
      task: { id: 1 }, // no allow_skip property
    });
    const onSkipWithComment = jest.fn();

    const { getByTestId } = render(
      <Provider store={mockStore}>
        <SkipButton disabled={false} store={mockStore as any} onSkipWithComment={onSkipWithComment} />
      </Provider>,
    );

    const button = getByTestId("skip-button");
    expect(button).not.toBeDisabled();
    expect(button).toHaveAttribute("title", "Cancel (skip) task [ Ctrl+Space ]");
  });

  test("Skip button enabled when allow_skip=null", () => {
    const mockStore = createMockStore({
      task: { id: 1, allow_skip: null },
    });
    const onSkipWithComment = jest.fn();

    const { getByTestId } = render(
      <Provider store={mockStore}>
        <SkipButton disabled={false} store={mockStore as any} onSkipWithComment={onSkipWithComment} />
      </Provider>,
    );

    const button = getByTestId("skip-button");
    expect(button).not.toBeDisabled();
    expect(button).toHaveAttribute("title", "Cancel (skip) task [ Ctrl+Space ]");
  });

  test("Skip button onClick doesn't trigger when allow_skip=false", () => {
    const mockStore = createMockStore({
      task: { id: 1, allow_skip: false },
      interfaces: ["skip"],
    });
    const onSkipWithComment = jest.fn();

    const { getByTestId } = render(
      <Provider store={mockStore}>
        <SkipButton disabled={false} store={mockStore as any} onSkipWithComment={onSkipWithComment} />
      </Provider>,
    );

    const button = getByTestId("skip-button");
    fireEvent.click(button);

    expect(onSkipWithComment).not.toHaveBeenCalled();
    expect(mockStore.skipTask).not.toHaveBeenCalled();
  });

  test("Skip button onClick triggers when allow_skip=true", async () => {
    const mockStore = createMockStore({
      task: { id: 1, allow_skip: true },
      interfaces: ["skip", "comments:skip"],
    });
    const onSkipWithComment = jest.fn();

    const { getByTestId } = render(
      <Provider store={mockStore}>
        <SkipButton disabled={false} store={mockStore as any} onSkipWithComment={onSkipWithComment} />
      </Provider>,
    );

    const button = getByTestId("skip-button");
    fireEvent.click(button);

    expect(onSkipWithComment).toHaveBeenCalled();
  });

  test("Skip button respects other disabled conditions", () => {
    const mockStore = createMockStore({
      task: { id: 1, allow_skip: true },
    });
    const onSkipWithComment = jest.fn();

    const { getByTestId } = render(
      <Provider store={mockStore}>
        <SkipButton disabled={true} store={mockStore as any} onSkipWithComment={onSkipWithComment} />
      </Provider>,
    );

    const button = getByTestId("skip-button");
    expect(button).toBeDisabled();
  });

  // Role-based tests (OW=Owner, AD=Admin, MA=Manager can force-skip)
  test("Skip button enabled when allow_skip=false but user is Owner (OW)", () => {
    setupAppSettings("OW");
    const mockStore = createMockStore({
      task: { id: 1, allow_skip: false },
    });
    const onSkipWithComment = jest.fn();

    const { getByTestId } = render(
      <Provider store={mockStore}>
        <SkipButton disabled={false} store={mockStore as any} onSkipWithComment={onSkipWithComment} />
      </Provider>,
    );

    const button = getByTestId("skip-button");
    expect(button).not.toBeDisabled();
    expect(button).toHaveAttribute("title", "Cancel (skip) task [ Ctrl+Space ]");
    // Check that info icon is shown for managers when task is unskippable
    expect(getByTestId("info-icon")).toBeInTheDocument();
  });

  test("Skip button enabled when allow_skip=false but user is Admin (AD)", () => {
    setupAppSettings("AD");
    const mockStore = createMockStore({
      task: { id: 1, allow_skip: false },
    });
    const onSkipWithComment = jest.fn();

    const { getByTestId } = render(
      <Provider store={mockStore}>
        <SkipButton disabled={false} store={mockStore as any} onSkipWithComment={onSkipWithComment} />
      </Provider>,
    );

    const button = getByTestId("skip-button");
    expect(button).not.toBeDisabled();
    expect(button).toHaveAttribute("title", "Cancel (skip) task [ Ctrl+Space ]");
    // Check that info icon is shown for managers when task is unskippable
    expect(getByTestId("info-icon")).toBeInTheDocument();
  });

  test("Skip button enabled when allow_skip=false but user is Manager (MA)", () => {
    setupAppSettings("MA");
    const mockStore = createMockStore({
      task: { id: 1, allow_skip: false },
    });
    const onSkipWithComment = jest.fn();

    const { getByTestId } = render(
      <Provider store={mockStore}>
        <SkipButton disabled={false} store={mockStore as any} onSkipWithComment={onSkipWithComment} />
      </Provider>,
    );

    const button = getByTestId("skip-button");
    expect(button).not.toBeDisabled();
    expect(button).toHaveAttribute("title", "Cancel (skip) task [ Ctrl+Space ]");
    // Check that info icon is shown for managers when task is unskippable
    expect(getByTestId("info-icon")).toBeInTheDocument();
  });

  test("Skip button disabled when allow_skip=false and user is Annotator (AN)", () => {
    setupAppSettings("AN");
    const mockStore = createMockStore({
      task: { id: 1, allow_skip: false },
    });
    const onSkipWithComment = jest.fn();

    const { getByTestId } = render(
      <Provider store={mockStore}>
        <SkipButton disabled={false} store={mockStore as any} onSkipWithComment={onSkipWithComment} />
      </Provider>,
    );

    const button = getByTestId("skip-button");
    expect(button).toBeDisabled();
    expect(button).toHaveAttribute("title", "This task cannot be skipped");
  });

  test("Skip button disabled when allow_skip=false and user is Reviewer (RE)", () => {
    setupAppSettings("RE");
    const mockStore = createMockStore({
      task: { id: 1, allow_skip: false },
    });
    const onSkipWithComment = jest.fn();

    const { getByTestId } = render(
      <Provider store={mockStore}>
        <SkipButton disabled={false} store={mockStore as any} onSkipWithComment={onSkipWithComment} />
      </Provider>,
    );

    const button = getByTestId("skip-button");
    expect(button).toBeDisabled();
    expect(button).toHaveAttribute("title", "This task cannot be skipped");
  });

  test("Skip button onClick triggers when allow_skip=false but user is Manager", () => {
    setupAppSettings("MA");
    const mockStore = createMockStore({
      task: { id: 1, allow_skip: false },
      interfaces: ["skip", "comments:skip"],
    });
    const onSkipWithComment = jest.fn();

    const { getByTestId } = render(
      <Provider store={mockStore}>
        <SkipButton disabled={false} store={mockStore as any} onSkipWithComment={onSkipWithComment} />
      </Provider>,
    );

    const button = getByTestId("skip-button");
    fireEvent.click(button);

    expect(onSkipWithComment).toHaveBeenCalled();
  });

  test("Skip button shows normal tooltip when allow_skip=true even for Manager", () => {
    setupAppSettings("MA");
    const mockStore = createMockStore({
      task: { id: 1, allow_skip: true },
    });
    const onSkipWithComment = jest.fn();

    const { getByTestId, queryByTestId } = render(
      <Provider store={mockStore}>
        <SkipButton disabled={false} store={mockStore as any} onSkipWithComment={onSkipWithComment} />
      </Provider>,
    );

    const button = getByTestId("skip-button");
    expect(button).not.toBeDisabled();
    // When task allows skip, show normal tooltip even if user is manager
    expect(button).toHaveAttribute("title", "Cancel (skip) task [ Ctrl+Space ]");
    // Info icon should not be shown when task allows skip
    expect(queryByTestId("info-icon")).not.toBeInTheDocument();
  });
});
